// 定义消息组件
// 定义消息组件
import {BaseElement, ChatStatus} from "./base.js";
import ChatMessage from './chat-message.js'
import ChatOptPanel from './chat-opt-panel.js'
import ChatTip from './chat-tip.js'
import ChatConfirmDialog from './chat-confirm-dialog.js'

import ChatMessagePanel from './chat-message-panel.js'
import ReferenceItem from './reference-item.js'
import MsgTip from './msg-tip.js'


// 注册Web Components
customElements.define('chat-message', ChatMessage);
customElements.define('chat-message-panel', ChatMessagePanel);
customElements.define('chat-tip', ChatTip);
customElements.define('msg-tip', MsgTip);
customElements.define('reference-item', ReferenceItem);
customElements.define('chat-opt-panel', ChatOptPanel);
customElements.define("chat-confirm-dialog", ChatConfirmDialog)

/**
 * AI聊天配置类
 */
class AiChatConfig {

    /**
     * 欢迎语
     * @type {null}
     */
    welcomeTip = null;
    /**
     * 是否显示头像
     * @type {boolean}
     */
    showAvatar = true;

    /**
     * 用户头像
     * @type {null}
     */
    userAvatar = null;
    /**
     * 机器人头像
     * @type {null}
     */
    assistantAvatar = null;

    /**
     * 是否显示清空聊天记录按钮
     * @type {boolean}
     */
    showClearMsgBtn = true;

    /**
     * 适配器
     * @type {null}
     */
    adapter = null;

    /**
     * websocket地址
     * @type {null}
     */
    websocketUrl = null;
    /**
     * websocket实例
     * @type {null}
     */
    websocketInstance = null; // 新增：外部WebSocket实例

    /**
     * 全局参数
     * @type {{}}
     */
    global = {}; //全局参数


    /**
     * chat实例
     * @type {null}
     */
    aiChat = null;

    /**
     * 应用id
     * @type {null}
     */
    app = null;

    /**
     * 会话id
     * @type {null}
     */
    sessionId = null;

    /**
     * 上传文件回调
     * @type {null}
     */
    onFileUpload = null;

    /**
     * markdown渲染回调
     * @param {*} content 原文本
     * @returns 渲染后的文本
     */
    onMarkdownRender = null;

    /**
     * 历史数据加载回调
     * @param {string|null} lastId - 最后一条消息的ID，为null时表示首次加载
     * @param {object} globalParams - 全局参数
     * @returns {Promise<Array|false>} - 返回历史消息数组或false
     */
    onHistoryLoad = async function (lastId, globalParams) {
        return false;
    };

    /**
     * 点击设置按钮时的回调
     * @type {null}
     */
    onSettingClick = null;

    /**
     * 消息接收时的回调
     * @type {null}
     */
    onMsgReceive = null;

    /**
     * 消息发送时的回调
     * @type {null}
     */
    onMsgSend = null;

    /**
     * 消息要删除时的回调
     * @type {null}
     */
    onMsgToDelete = null;

    /**
     * 清空消息的回调
     * @type {null}
     */
    onClearMsg = null;

    /**
     * 根据json设置自己的属性
     * @param json
     */
    from(json) {
        // console.log("AiChatConfig.from", json)
        if (json) {
            this.welcomeTip = json.welcomeTip;
            this.websocketUrl = json.websocketUrl;
            this.app = json.app;
            this.showAvatar = json.showAvatar??true;
            this.userAvatar = json.userAvatar;
            this.assistantAvatar = json.assistantAvatar;
            this.showClearMsgBtn = json.showClearMsgBtn??true;
            this.adapter = json.adapter;
            this.sessionId = json.sessionId;
            this.websocketInstance = json.websocketInstance;
            this.onFileUpload = json.onFileUpload;
            this.global = json.global ?? {};

            if (typeof json.onHistoryLoad === 'function') {
                this.onHistoryLoad = json.onHistoryLoad;

            }

            if (typeof json.onMarkdownRender === 'function') {
                this.onMarkdownRender = json.onMarkdownRender;
            }

            if (typeof json.onSettingClick === 'function') {
                this.onSettingClick = json.onSettingClick;
            }
            if (typeof json.onMsgReceive === 'function') {
                this.onMsgReceive = json.onMsgReceive;
            }
            if (typeof json.onMsgSend === 'function') {
                this.onMsgSend = json.onMsgSend;
            }
            if (typeof json.onMsgToDelete === 'function') {
                this.onMsgToDelete = json.onMsgToDelete;
            }
            if (typeof json.onClearMsg === 'function') {
                this.onClearMsg = json.onClearMsg;
            }
        }
        return this;
    }

}




/**
 * AI聊天窗口类
 */
class AiChat {

    /**
     * 容器
     * @type {null}
     */
    container = null;


    /**
     * 消息面板
     * @type {null}
     */
    messagePanel = null;
    /**
     * 操作面板
     * @type {null}
     */
    optPanel = null;

    /**
     * 确认对话框
     * @type {null}
     */
    confirmDialog = null;

    statusListener = []


    status = ChatStatus.IS_WAITING;

    /**
     * 是否正在加载历史记录
     * @type {boolean}
     */
    isLoadingHistory = false;


    /**
     * 正在处理的消息
     * @type {null}
     */
    processingMsg = null;

    /**
     * 消息监听器
     * @type {[]}
     */
    messageListener = []

    /**
     * websocket连接
     * @type {{instance: null, isSelf: boolean}}
     */
    ws = {
        instance: null,
        isSelf: true, //是否是自己维护的链接
    }

    constructor(element, config) {
        this.element = element;
        this.config = new AiChatConfig().from(config);
        this.config.aiChat = this;
        this.onSocketOpened = this.onSocketOpened.bind(this);
        this.onSocketClosed = this.onSocketClosed.bind(this);
        this.onmessage = this.onmessage.bind(this);

        this.init();
    }

    addChatStatusListener(listener) {
        this.statusListener.push(listener);
    }

    /**
     * 添加消息监听器
     * @param listener
     */
    addChatMessageListener(listener) {
        this.messageListener.push(listener);
    }


    /**
     * 销毁实例
     */
    destroy() {
        console.warn("AiChat实例开始销毁")
        this.closeWebSocket();
        this.element.removeChild(this.container)
    }


    init() {
        if (this.element) {
            this.element.innerHTML = `
                <div class="ai-chat-container">
                    <chat-message-panel ></chat-message-panel>
                    <chat-opt-panel></chat-opt-panel>
                </div>
                <style>
                    .ai-chat-container {
                        height: 100%;
                        background-image: linear-gradient(rgb(248, 250, 252), rgb(255, 255, 255));
                        flex:1;
                        overflow: hidden;
                        display: flex;
                        flex-direction: column;
                        tab-size: 4;
                        -webkit-text-size-adjust: 100%;
                        font-feature-settings: normal;
                        font-variation-settings: normal;
                        -webkit-tap-highlight-color: transparent;
                    }
                    @media (width > 640px) {
                        .ai-chat-container {
                            font-size: 16px;
                        }
                    }
                </style>
            `;

            this.container = this.element.querySelector('.ai-chat-container');
            this.messagePanel = this.container.querySelector("chat-message-panel");
            this.messagePanel.receive("chatInstance", this);
            this.optPanel = this.container.querySelector("chat-opt-panel");
            this.optPanel.receive("chatInstance", this);

            //注册一个确认弹出框
            this.confirmDialog = document.createElement("chat-confirm-dialog");
            document.body.appendChild(this.confirmDialog);
            this.loadHistoryData(null);
        }

        this.setupWebSocket();
    }


    isFirstLoadHistory = true;
    loadHistoryData(startId) {
        if (!this.config.onHistoryLoad || this.isLoadingHistory) return Promise.reject('没有更多数据了');
        this.isLoadingHistory = true;
        return new Promise((resolve, reject) => {
            this.config.onHistoryLoad(startId, this.config.global).then((data) => {
                if (!data) return;
                if (data.msgs?.length) {
                    this.isLoadingHistory = false;
                    let msgs =  data.msgs.reverse();
                    for (const msg of msgs) {
                        this.handleMessage({ ...msg,  action: 'insert' });
                    }
                    if (this.isFirstLoadHistory) {
                        this.isFirstLoadHistory = false;
                        //滚动到底部
                        setTimeout(() => {
                            this.messagePanel.scrollToBottom();
                        },20)

                    }
                    resolve();
                } else {
                    reject('没有更多数据了');
                }
                console.debug(data.status, this.config.welcomeTip)
                if (data.status == 'over' && this.config.welcomeTip) {
                    //插入欢迎语
                    console.debug("插入欢迎语")
                    this.handleMessage({data:{role:'assistant', renderType:'markdown',content:{text:this.config.welcomeTip}}, action:'insert'});
                }

            })
        })


    }


    closeWebSocket() {
        if (this.ws.instance) {
            // 清理旧的监听器
            this.ws.instance.removeEventListener('message', this.onmessage);
            this.ws.instance.removeEventListener('open', this.onSocketOpened);
            this.ws.instance.removeEventListener('close', this.onSocketClosed);
            if (this.ws.isSelf) {
                console.warn("websocket连接即将被关闭...")
                //自己的内部的socket链接
                this.ws.instance.close();
            }
        }
    }


    setupWebSocket() {
        this.closeWebSocket();
        if (this.config.websocketInstance) {
            // 使用外部WebSocket实例
            this.ws.instance = this.config.websocketInstance;
            this.ws.instance.addEventListener('message', this.onmessage);
            // 更新连接状态
            this.ws.instance.addEventListener('open', this.onSocketOpened);
            this.ws.instance.addEventListener('close', this.onSocketClosed);
            this.ws.isSelf = false;

            this.updateChatStatus(this.ws.instance.readyState === WebSocket.OPEN ? ChatStatus.IS_READY : ChatStatus.IS_WAITING);
        } else if (this.config.websocketUrl) {
            // 使用内部WebSocket连接
            this.connectWebSocket();
        }
    }

    connectWebSocket() {


        this.ws.instance = new WebSocket(this.config.websocketUrl);

        this.ws.instance.addEventListener('open', this.onSocketOpened);

        this.ws.instance.addEventListener('message', this.onmessage);

        this.ws.instance.onclose = () => {
            this.onSocketClosed()
            if (this.config.websocketUrl) {  // 只有在使用URL模式时才自动重连
                setTimeout(() => this.connectWebSocket(), 3000);
            }
        };

        this.ws.instance.onerror = (error) => {
            console.error('WebSocket error:', error);
            this.updateChatStatus(ChatStatus.DISCONNECTED);
        };
        this.ws.isSelf = true;
    }

    /**
     * 发送消息
     * @param message
     * @returns {boolean}
     */
    sendMessage(message) {
        if (this.status != ChatStatus.IS_READY && message.action !== 'cancel') {
            console.error('当前状态不是就绪状态，无法发送消息', this.status);
            return false;
        }
        this.updateChatStatus(ChatStatus.IS_WAITING)
        const msg = this.processSendMessage(message);
        this.ws.instance.send(JSON.stringify(this.adaptMsg(msg)));
        this.processingMsg = msg
        this.handleMessage(msg)
        if (this.config.onMsgSend) {
            this.config.onMsgSend(msg)
        }
        return true;
    }

    /**
     * 取消当前聊天
     */
    cancelCurrentChat() {
        if (this.processingMsg) {
            this.sendMessage({ ...this.processingMsg, 'action': "cancel" })
        }
    }

    handleMessage(msg) {
        switch (msg.action) {
            case 'response':
                this.updateChatStatus(ChatStatus.IS_RECEIVING);
                break;
            case 'over':
                this.updateChatStatus(ChatStatus.IS_READY);
                break;
            case 'error':
                this.updateChatStatus(ChatStatus.IS_RECEIVING);
                break;
        }
        this.messageListener.forEach(listener => listener(msg))
        if (this.config.onMsgReceive) {
            this.config.onMsgReceive(msg)
        }
    }


    /**
     * 处理要发送的消息
     * @param message
     * @returns {string}
     */
    processSendMessage(message) {
		console.log("发送消息");
        let data = {
            sessionId: this.config.sessionId,
            app: this.config.app,
            flag: this.generateMsgFlag(), //msg标识，方便后端返回数据后找到该数据做后续处理
            ...message,
            global: this.config.global
        };


        return data;
    }

    adaptMsg(msg) {
        if (this.config.adapter) {
            switch (this.config.adapter) {
                case 'jbolt':
                    return this.adaptJBolt(msg);
            }
        }
        return msg;
    }

    /**
     * 对jbolt进行适配
     */
    adaptJBolt(data) {
        if (data.command) {
            //解封
            return data.data;
        } else {
            //包装
            return {
                command: 'ai_chat',
                type: 1,
                data: data
            }
        }
    }


    /**
     * 生成消息标识
     * @returns {string} 时间戳+4位随机字符串
     */
    generateMsgFlag() {
        const timestamp = Date.now();
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let randomStr = '';
        for (let i = 0; i < 4; i++) {
            randomStr += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        return `${timestamp}${randomStr}`;
    }


    onmessage(event) {
        try {
            let message = JSON.parse(event.data);

            if (this.config.adapter) {
                message = this.adaptMsg(message);
            }
            if ((this.config.app && message.app != this.config.app) || (this.config.sessionId && message.sessionId != this.config.sessionId)) {
                //不是自己的消息，不做任何处理
                return;
            }
            // console.debug("接收到消息：", message)
            this.handleMessage(message)
        } catch (error) {
            console.error('Error parsing message:', error);
        }
    }

    onSocketOpened() {
        console.log('WebSocket connected');
        this.updateChatStatus(ChatStatus.IS_READY);
    }

    onSocketClosed() {
        console.log('WebSocket disconnected');
        this.updateChatStatus(ChatStatus.DISCONNECTED);
    }

    // 更新连接状态的方法
    updateChatStatus(status) {
        this.status = status;
        this.statusListener.forEach(listener => listener(status))

    }

    // 更新WebSocket实例的方法
    updateWebSocket(newInstance) {

        this.config.websocketInstance = newInstance;
        this.config.websocketUrl = null;  // 清除URL配置
        this.setupWebSocket();
    }

    // 更新WebSocket URL的方法
    updateWebSocketUrl(newUrl) {
        this.config.websocketUrl = newUrl;
        this.config.websocketInstance = null;  // 清除实例配置
        this.setupWebSocket();
    }

    /**
     * 更新全局参数
     * @param newParams
     */
    updateGlobal(newParams) {
        this.config.global = newParams;
    }


    deleteMsg(flag, msgId) {
        console.debug("开始删除", flag, msgId)
        if (this.config.onMsgToDelete) {
            const res = this.config.onMsgToDelete(msgId);
            if (res === true) {
                this.messagePanel.deleteMessage(flag)
            } else if (res instanceof Promise) {
                res.then((resolvedValue) => {
                    if (resolvedValue === true) { // Check the resolved value
                        this.messagePanel.deleteMessage(flag);
                    }
                })
            }
        } else {
            throw new Error('onMsgToDelete is not defined');
        }
    }

    /**
     * 重新生成内容
     * @param flag
     */
    regenerate(flag, msgId) {
        if (this.status != ChatStatus.IS_READY) {
            throw new Error("当前有消息正在接收，请等待结束后再重新生成");
        }
        this.sendMessage({
            action: "regenerate",
            flag,
            msgId: msgId
        })
    }

}

export default AiChat;